package edu.towson.cosc716.gui;

import java.lang.Integer;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.ScrollPaneLayout;
import javax.swing.table.TableColumn;

import edu.towson.cosc716.interfaces.ObservableInterface;
import edu.towson.cosc716.interfaces.ObserverInterface;
import edu.towson.cosc716.iterators.GetTabByTable;
import edu.towson.cosc716.models.Chef;
import edu.towson.cosc716.models.Constants;
import edu.towson.cosc716.models.DiningRoom;
import edu.towson.cosc716.models.InformationAggregator;
import edu.towson.cosc716.models.MenuItem;
import edu.towson.cosc716.models.Order;
import edu.towson.cosc716.models.Table;


// TODO: Auto-generated Javadoc
/**
 * The Class SimulationMoniter.
 */
public class SimulationMoniter extends JFrame implements ObserverInterface, ObservableInterface {
	
	/** The content pane. */
	private Container contentPane;
	
	// Main JPanels
	/** The north. */
	private JPanel north;
	
	/** The central. */
	private JPanel central;
	
	/** The south. */
	private JPanel south;
	
	
	// North's JPanels
	/** The seating view. */
	private JPanel seatingView;
	
	/** The kitchen view. */
	private JPanel kitchenView;
	
	/** The offers view. */
	private JPanel offersView;
	
	//  seatingView's JPanels
	/** The table map view. */
	private JPanel tableMapView;
	
	/** The tables view. */
	private JPanel tablesView;
	
	/** The seating wait view. */
	private JPanel seatingWaitView;
	
	/** The cust waiting view. */
	private JPanel custWaitingView;
	
	/** The estimated wait. */
	private JPanel estimatedWait;
	
	// kitchenView's JPanels
	/** The kitchen map view. */
	private JPanel kitchenMapView;
	
	/** The kitchen chef view. */
	private JPanel kitchenChefView;
	
	/** The kitchen order view. */
	private JPanel kitchenOrderView;
	
	// offerView's JPanels
	/** The offer content view. */
	private JPanel offerContentView;
	
	// Central JPanel
	
	
	

	/** The observers. */
	private List<ObserverInterface> observers;
	
	/** The small. */
	private Font small = new Font("small", Font.PLAIN, 10);
	
	/** The tiny. */
	private Font tiny = new Font("Tiny", Font.PLAIN, 8);
	
	/** The dark green. */
	private Color darkGreen = new Color(0,100,0);
	
	/** The information aggregator. */
	private InformationAggregator informationAggregator;
	
	/**
	 * Instantiates a new simulation moniter.
	 *
	 * @param informationAggregator the information aggregator
	 */
	public SimulationMoniter(InformationAggregator informationAggregator) {
		this.informationAggregator = informationAggregator;
		observers = new ArrayList<ObserverInterface>();
		
		// Register as Observer
		this.informationAggregator.diningRoom.addObserver(this);
		this.informationAggregator.seatingQueue.addObserver(this);
		
		// Build main window
		setTitle("Simulation Monitor");
		setSize(1024, 768);
		setLocation(10, 200);
		setLayout(new BorderLayout());
		contentPane = new Container();
		contentPane.setLayout(new GridLayout(3, 1));
		add(contentPane);	
		
		// Build and Add Main Panels
		north = new JPanel();
		north.setName("north");
		central = new JPanel();
		central.setName("central");
		south = new JPanel();
		south.setName("south");
		contentPane.add(north, 0);
		contentPane.add(central, 1);
		contentPane.add(south, 2);
		
		
		// Build North JPanel
		north.setLayout(new GridLayout(1,3));
		//north.setBorder(BorderFactory.createLineBorder(Color.black));
		seatingView = new JPanel();
		seatingView.setName("seatingView");
		kitchenView = new JPanel();
		kitchenView.setName("kitchenView");
		offersView = new JPanel();
		offersView.setName("offersView");
		north.add(seatingView, 0);
		north.add(kitchenView, 1);
		north.add(offersView, 2);
		
		
		// Build seating view
		seatingView.setLayout(new GridLayout(2, 1));
		tableMapView = new JPanel();
		tablesView = new JPanel();
		seatingWaitView = new JPanel();
		seatingView.add(tableMapView, 0);
		seatingView.add(seatingWaitView, 1);
		custWaitingView = new JPanel();
		estimatedWait = new JPanel();
		
		tableMapView.setLayout(new GridLayout(2,1));
		JLabel tableLabel = new JLabel("Table Map",JLabel.CENTER);		
		tableMapView.add(tableLabel, 0);
		tableMapView.add(tablesView, 1);
		tablesView.setLayout(new GridLayout(5,4));
		Enumeration tables = informationAggregator.diningRoom.getAllTables();
		while (tables.hasMoreElements()) {
			Table table = (Table)tables.nextElement();
			JButton button = new JButton(String.valueOf(table.getTableId()));
			button.setName(String.valueOf(table.getTableId()));
			tablesView.add(button);
		}
		updateTables();
		
		seatingWaitView.setLayout(new GridLayout(1,2));
		seatingWaitView.add(estimatedWait, 0);
		seatingWaitView.add(custWaitingView, 1);
		estimatedWait.setLayout(new GridLayout(2,1));
		JLabel estimateWaitLabel = new JLabel("Avg Wait Time",JLabel.CENTER);
		estimateWaitLabel.setFont(small);
		estimateWaitLabel.setName("estimatedWaitLabel");
		JLabel estimatesWaitInfo = new JLabel("15 Min",JLabel.CENTER);
		estimatesWaitInfo.setFont(small);
		estimatesWaitInfo.setName("estimatedWaitInfo");
		estimatedWait.add(estimateWaitLabel, 0);
		estimatedWait.add(estimatesWaitInfo, 1);
		custWaitingView.setLayout(new GridLayout(2,1));
		JLabel seatingCountLabel = new JLabel("Customers Waiting",JLabel.CENTER);
		seatingCountLabel.setFont(small);
		seatingCountLabel.setName("seatingCountLabel");
		JLabel seatingCountInfo = new JLabel("0",JLabel.CENTER);
		seatingCountInfo.setFont(small);
		seatingCountInfo.setName("seatingCountInfo");
		custWaitingView.add(seatingCountLabel, 0);
		custWaitingView.add(seatingCountInfo, 1);
		
		// Kitchen View
		kitchenView.setLayout(new GridLayout(3,1));
		kitchenMapView = new JPanel();
		kitchenChefView = new JPanel();
		kitchenOrderView = new JPanel();
		kitchenView.add(kitchenMapView, 0);
		kitchenView.add(kitchenOrderView, 1);
		kitchenMapView.setLayout(new GridLayout(2, 1));
		JLabel kitchenLabel = new JLabel("Kitchen", JLabel.CENTER);
		kitchenLabel.setName("kitchenLabel");
		kitchenMapView.add(kitchenLabel, 0);
		kitchenMapView.add(kitchenChefView, 1);
		kitchenChefView.setLayout(new GridLayout(1, 5));
		kitchenOrderView.setLayout(new GridLayout(2,2));
		JLabel kitchenOrderCountLabel = new JLabel("Queue Count", JLabel.CENTER);
		kitchenOrderCountLabel.setName("kitchenOrderCountLabel");
		kitchenOrderCountLabel.setFont(small);
		JLabel kitchenOrderCountInfo = new JLabel("0", JLabel.CENTER);
		kitchenOrderCountInfo.setName("kitchenOrderCountInfo");
		kitchenOrderCountInfo.setFont(small);
		JLabel kitchenOrderAvgTimeLabel = new JLabel("Avg Prep Time", JLabel.CENTER);
		kitchenOrderAvgTimeLabel.setName("kitchenOrderAvgTimeLabel");
		kitchenOrderAvgTimeLabel.setFont(small);
		JLabel kitchenOrderAvgTimeInfo = new JLabel("0", JLabel.CENTER);
		kitchenOrderAvgTimeInfo.setName("kitchenOrderAvgTimeInfo");
		kitchenOrderAvgTimeInfo.setFont(small);
		kitchenOrderView.add(kitchenOrderCountLabel, 0);
		kitchenOrderView.add(kitchenOrderAvgTimeLabel, 1);
		kitchenOrderView.add(kitchenOrderCountInfo, 2);
		kitchenOrderView.add(kitchenOrderAvgTimeInfo, 3);
		for (Map.Entry<Chef, Order> entry : informationAggregator.kitchen.entrySet()) {
			if (entry.getValue() == null) {
				JButton button = new JButton(entry.getKey().getName() + ": None");
				button.setName("chef" + entry.getKey().getChefId());
				kitchenChefView.add(button);
				button.setFont(tiny);
				button.repaint();
			} else {
				if (entry.getValue().getMenuItemId() < 1) {
					JButton button = new JButton(entry.getKey().getName() + ": None");
					button.setName("chef" + entry.getKey().getChefId());
					kitchenChefView.add(button);
					button.setFont(tiny);
					button.repaint();
				} else {
					JButton button = new JButton(entry.getKey().getName() + ":" + informationAggregator.menu.find(entry.getValue().getMenuItemId()).getName());
					button.setName("chef" + entry.getKey().getChefId());
					kitchenChefView.add(button);
					button.setFont(tiny);
					button.repaint();
				}
			}
		}
		kitchenChefView.repaint();
		
		
		// Build offers view
		String[] colomnNames = {"Offer", "Count"};
		Object[][] offerData = {
				{"10% Discount" , new Integer(2)  }, {"20% Discount", new Integer(4) }
				};
		offersView.setLayout(new GridLayout(2, 1));
		offerContentView = new JPanel();
		offerContentView.setLayout(new GridLayout(2,1));
		JLabel offersLabel = new JLabel("Offers", JLabel.CENTER);
		offersLabel.setName("offersLabel");
		JTable offersTable = new JTable(offerData,colomnNames);
		offersView.add(offersLabel, 0);
		offerContentView.add(offersTable.getTableHeader(),0);
		offerContentView.add(offersTable, 1);
		offersView.add(offerContentView, 1);
	
		// Central view
		central.setLayout(new GridLayout(2, 1));
		JScrollPane menuItemsScrollPane = new JScrollPane();
		Enumeration menuItems = informationAggregator.menu.getAllMenuItems();
		int count = 0;
		while (menuItems.hasMoreElements()) {
			menuItems.nextElement();
			count++;
		}
		Object[][] menuItemDataObjects = new Object[count][5];
		menuItems = informationAggregator.menu.getAllMenuItems();
		int i = 0;
		while (menuItems.hasMoreElements()) {
			MenuItem menuItem = (MenuItem)menuItems.nextElement();
			Object[] menuItemInfo = { menuItem.getName(), menuItem.getBasePrice(), menuItem.getCurrentPrice(), menuItem.getAvgRating(), menuItem.getInventory() };			
			for (int j = 0; j < menuItemInfo.length; j++) {
				menuItemDataObjects[i][j] = menuItemInfo[j]; 
			}
			i++;
		}
		String[] columnNames = {"Name", "Base Price", "Current Price", "Rating", "Inventory"};
		JTable menuItemsTable = new JTable(menuItemDataObjects, columnNames);
		menuItemsScrollPane.setLayout(new ScrollPaneLayout());
		menuItemsScrollPane.add(menuItemsTable);
		central.add(menuItemsTable.getTableHeader(), 0);
		central.add(menuItemsTable,1);

		
				
		//  Terminate program listener
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
				
			}
		});
		
	}
	

	/* (non-Javadoc)
	 * @see edu.towson.cosc716.interfaces.ObserverInterface#update(edu.towson.cosc716.interfaces.ObservableInterface)
	 */
	@Override
	public void update(ObservableInterface o) {
		// If we get time add "getType" method to all models/ ObservableInterface to allow to figure out what type object is and act accordingly.
		updateTables();
		updateKitchen();
		updateCustomerWaiting();
		updateOrders();
		updateMenuItemsView();

	}

	/* (non-Javadoc)
	 * @see edu.towson.cosc716.interfaces.ObservableInterface#addObserver(edu.towson.cosc716.interfaces.ObserverInterface)
	 */
	@Override
	public void addObserver(ObserverInterface o) {
		
		
	}

	/* (non-Javadoc)
	 * @see edu.towson.cosc716.interfaces.ObservableInterface#removeObserver(edu.towson.cosc716.interfaces.ObserverInterface)
	 */
	@Override
	public void removeObserver(ObserverInterface o) {
		// TODO Auto-generated method stub
		
	}
	
	/**
	 * Update menu items view.
	 */
	public void updateMenuItemsView() {
		JTable jtable = (JTable)central.getComponent(1);
		
		Enumeration menuItems = informationAggregator.menu.getAllMenuItems();
		int count = 0;
		while (menuItems.hasMoreElements()) {
			menuItems.nextElement();
			count++;
		}
		Object[][] menuItemDataObjects = new Object[count][5];
		menuItems = informationAggregator.menu.getAllMenuItems();
		int i = 0;
		while (menuItems.hasMoreElements()) {
			MenuItem menuItem = (MenuItem)menuItems.nextElement();
			Object[] menuItemInfo = { menuItem.getName(), menuItem.getBasePrice(), menuItem.getCurrentPrice(), menuItem.getAvgRating(), menuItem.getInventory() };			
			for (int j = 0; j < menuItemInfo.length; j++) {
					menuItemDataObjects[i][j] = menuItemInfo[j];				
			}
			i++;
		}
		Object[] columnNames = {"Name", "Base Price", "Current Price", "Rating", "Inventory"};
		JTable menuItemsTable = new JTable(menuItemDataObjects, columnNames);
		central.removeAll();
		central.add(menuItemsTable.getTableHeader(),0);
		central.add(menuItemsTable, 1);
		menuItemsTable.validate();
	}
	
	/**
	 * Update customer waiting.
	 */
	public void updateCustomerWaiting() {
		JLabel comp = (JLabel)custWaitingView.getComponent(1);
		comp.setText(String.valueOf(informationAggregator.seatingQueue.size()));
		comp.repaint();
		comp = (JLabel) estimatedWait.getComponent(1);
		comp.setText(String.valueOf(informationAggregator.avgWaitTime.getAverage()));
		comp.repaint();
	}
	
	/**
	 * Update tables.
	 */
	public void updateTables() {
		Component[] components = tablesView.getComponents();
		Enumeration tables = informationAggregator.diningRoom.getAllTables();
		while (tables.hasMoreElements()) {
			Table table = (Table)tables.nextElement();
			for (Component comp : components) {
				if (table.getTableId() == Integer.parseInt(comp.getName())) {
					if (table.isOccupied()) {
						comp.setForeground(darkGreen);
					} else {
						comp.setForeground(Color.RED);		
					}
					comp.repaint();
				}
			}
		}

	}
	
	/**
	 * Update kitchen.
	 */
	public void updateKitchen() {
		int compCount = kitchenChefView.getComponentCount();
		List<Chef> chefs = new ArrayList<Chef>();
		List<Order> orders = new ArrayList<Order>();
		for (Map.Entry<Chef,Order> entry : informationAggregator.kitchen.entrySet()) {
			chefs.add(entry.getKey());
			orders.add(entry.getValue());
		}
		for (int i = 0; i < compCount; i++) {
			JButton button = (JButton) kitchenChefView.getComponent(i);
			if (orders.get(i) == null) {
				button.setText(chefs.get(i).getName() + " : None");
			} else {
				button.setText(chefs.get(i).getName() + " : " + informationAggregator.menu.find(orders.get(i).getMenuItemId()).getName());
			}
			button.setFont(tiny);
			button.repaint();
		}			
	}
	
	/**
	 * Update orders.
	 */
	public void updateOrders() {
		JLabel comp = (JLabel)kitchenOrderView.getComponent(2);
		comp.setText(String.valueOf(informationAggregator.orders.getSize()));
		comp.repaint();
		comp = (JLabel)kitchenOrderView.getComponent(3);
		comp.setText(String.valueOf(informationAggregator.avgPrepTime.getAverage()));
		comp.repaint();
		kitchenOrderView.repaint();
	}
	
	/**
	 * Sets the table status.
	 *
	 * @param name the new table status
	 */
	public void setTableStatus(String name) {
		Component[] components = tablesView.getComponents();
		for (Component comp : components) {
			if (name.equals(comp.getName())) {
				comp.setForeground(Color.BLUE);
				comp.repaint();
			}
		}

	}


	/* (non-Javadoc)
	 * @see edu.towson.cosc716.interfaces.ObservableInterface#getType()
	 */
	@Override
	public String getType() {
		return Constants.ObjectTypes.SIMULATIONMONITOR;
	}
}
